//  This file is part of MANTIS OS, Operating System
//  See http://mantis.cs.colorado.edu/
//
//  Copyright (C) 2003-2005 University of Colorado, Boulder
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the mos license (see file LICENSE)

/**************************************************************************/
/* File:    cortex.c                                                      */
/* Author: Adam Torgerson adam.torgerson@colorado.edu                     */
/*   Date: 06/08/04                                                       */
/*                                                                        */
/* A log viewer application for xml files generated by gateway xml logger */
/**************************************************************************/

#include <gtk/gtk.h>
#include <glade/glade.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "logview.h"
#include "cortex/include/net_event.h"

GtkWidget *window;
GtkWidget *treeview;
GtkTreeStore *tree_store;
GtkCellRenderer *renderer;
GtkTreeSelection *selection;
GtkTreeViewColumn *column;

enum {
   COLUMN_ID,
   COLUMN_LIGHT,
   COLUMN_TEMP,
   COLUMN_TIME,
   NUM_COLUMNS
};

void about_callback (GtkMenuItem *menu_item, gpointer data)
{
   g_warning ("About unimplemented");
}

xmlXPathObjectPtr run_xpath (xmlDocPtr doc, xmlChar *xpath_request)
{
   xmlXPathObjectPtr xpath_results;
   xmlXPathContextPtr context;

   context = xmlXPathNewContext (doc);
   xpath_results = xmlXPathEvalExpression (xpath_request, context);
   if (!xpath_results) {
      g_warning ("XPath expression '%s' did not return anything", xpath_request);
      xmlXPathFreeContext (context);
      return NULL;
   }
   if (xmlXPathNodeSetIsEmpty (xpath_results->nodesetval)) {
      g_warning ("No result found for XPath expr '%s'", xpath_request);
      xmlXPathFreeContext (context);
      return NULL;
   }

   xmlXPathFreeContext (context);
   return xpath_results;
}

void xml_open_file_helper (xmlNodePtr parent_node)
{
   xmlNodePtr node = parent_node;
   gint node_id = -1;
   gint light = -1;
   gint temp = -1;
   gint time = -1;

   while (node != NULL) {
      if (node->type == XML_ELEMENT_NODE) {
	 if (strcmp (node->name, "node_id") == 0)
	    node_id = atoi (xmlNodeGetContent (node));
	 if (strcmp (node->name, "light") == 0)
	    light = atoi (xmlNodeGetContent (node));
	 if (strcmp (node->name, "temp") == 0)
	    temp = atoi (xmlNodeGetContent (node));
	 if (strcmp (node->name, "time") == 0)
	    time = atoi (xmlNodeGetContent (node));
      }
      node = node->next;
   }

   if (node_id == -1 || light == -1 || temp == -1 || time == -1) {
      g_warning ("Not a complete xml log?: id:%d light:%d temp:%d time:%d",
		 node_id, light, temp, time);
   }

   gchar *time_string = ctime ((time_t *)&time);
   gchar *index;
   GtkTreeIter iter_parent;

   index = g_strrstr (time_string, "\n");
   if (index)
      *index = '\0';
   
   gtk_tree_store_append (tree_store, &iter_parent, NULL);
   gtk_tree_store_set (tree_store, &iter_parent, COLUMN_ID, node_id,
		       COLUMN_LIGHT, light, COLUMN_TEMP, temp,
		       COLUMN_TIME, time_string, -1);
}

void xml_open_file (gchar *filename)
{
   gint i;
   
   xmlDocPtr xml_doc = xmlParseFile (filename);
   if (xml_doc == NULL) {
      g_warning ("Couldn't parse '%s'", filename);
      return;
   }

   xmlXPathObjectPtr xpath_results;
   xpath_results = run_xpath (xml_doc, "//sensor_network_logger/light_temp_event");
   if (xpath_results) {
      xmlNodeSetPtr node_set = xpath_results->nodesetval;
      for (i = 0; i < node_set->nodeNr; i++) {
	 xmlNodePtr node = node_set->nodeTab[i]->xmlChildrenNode;
	 xml_open_file_helper (node);
      }
   } else {
      g_warning ("Couldn't find anything in the log file");
      return;
   }

   xmlFreeDoc (xml_doc);
   xmlCleanupParser ();
}

void open_callback_helper (GtkDialog *chooser, gint arg1, gpointer data)
{
   gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));

   if (arg1 == GTK_RESPONSE_CANCEL)
      goto end;

   if (filename == NULL) {
      g_warning ("Tried to open a NULL filename");
      goto end;
   }

   xml_open_file (filename);
   goto end;

end:
   gtk_widget_destroy (GTK_WIDGET (chooser));
}

void open_callback (GtkMenuItem *menu_item, gpointer data)
{
   GtkWidget *dialog = gtk_file_chooser_dialog_new ("Open XML Log File",
						    GTK_WINDOW (window),
						    GTK_FILE_CHOOSER_ACTION_OPEN,
						    GTK_STOCK_CANCEL,
						    GTK_RESPONSE_CANCEL,
						    GTK_STOCK_OPEN,
						    GTK_RESPONSE_ACCEPT,
						    NULL);
   gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
   g_signal_connect (G_OBJECT (dialog), "response",
		     G_CALLBACK (open_callback_helper),
		     NULL);

   gtk_widget_show (dialog);
}

void quit_callback (GtkMenuItem *menu_item, gpointer data)
{
   printf ("Exiting\n");
   exit (0);
}

void create_treeview (void)
{
   tree_store = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_INT, G_TYPE_INT,
				    G_TYPE_INT, G_TYPE_STRING);

   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store));
   g_object_unref (tree_store);

   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Node ID",
						      renderer,
						      "text",
						      COLUMN_ID,
						      NULL);
   gtk_tree_view_column_set_sort_column_id(column, COLUMN_ID);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Light",
						      renderer,
						      "text",
						      COLUMN_LIGHT,
						      NULL);
   gtk_tree_view_column_set_sort_column_id(column, COLUMN_LIGHT);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Temp",
						      renderer,
						      "text",
						      COLUMN_TEMP,
						      NULL);
   gtk_tree_view_column_set_sort_column_id(column, COLUMN_TEMP);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes ("Time",
						      renderer,
						      "text",
						      COLUMN_TIME,
						      NULL);
   gtk_tree_view_column_set_sort_column_id(column, COLUMN_TIME);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

   gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tree_store),
					COLUMN_ID, GTK_SORT_ASCENDING);
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);

   gtk_widget_show (treeview);

   return;
}

int main (int argc, char *argv[])
{
   GladeXML *xml;
   
   gtk_init (&argc, &argv);
   glade_init ();

   xml = glade_xml_new (GLADE_FILE, NULL, NULL);
   if (!xml) {
      g_warning ("Couldn't open glade xml file");
      return -1;
   }

   window = glade_xml_get_widget (xml, "main_window");
   
   GtkWidget *scrolled_window = glade_xml_get_widget (xml, "scrolledwindow1");
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
				   GTK_POLICY_AUTOMATIC,
				   GTK_POLICY_AUTOMATIC);
   create_treeview ();
   gtk_container_add (GTK_CONTAINER (scrolled_window), treeview);
   
   gtk_widget_show_all (window);
   glade_xml_signal_autoconnect (xml);

   gtk_main ();
   
   return 0;
}
